package nosql.query;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import nosql.MysqlConnector;
import nosql.property.RecommendedCondition;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;

/**
 * ConditionRecommender recommends condition properties according 
 * to selected properties.
 * @author Yexi Jiang <http://sites.google.com/site/yexijiang/>
 *
 */
public class BaselineConditionRecommender {
	private MysqlConnector connector;
	private String[] selectedProperties;
	private String[] selectedConditions;
	private JSONArray queryConditions;
	
	public BaselineConditionRecommender(MysqlConnector connector, String[] properties, JSONArray queryConditions){
		this.connector = connector;
		selectedProperties = properties;
		this.queryConditions = queryConditions;
	}
	
	public List<String> getRecommendedCondition(){
		List<String> recommendedConditions = null;
		Set<String> addedCondition = new HashSet<String>();
		try{
			recommendedConditions = getRelatedPropertyByPropertyNames(selectedProperties);
			
			//	extra filter process
			JSONParser parser = new JSONParser();
			if(queryConditions != null){
				for (Object subObj : queryConditions) {
					Object parsedObj = parser.parse(subObj.toString());
					if (parsedObj instanceof JSONObject) {
						JSONObject jsonObj = (JSONObject) parsedObj;
						String name = jsonObj.get("name").toString();
						System.out.println("add:" + name);
						addedCondition.add(name);
					}
				}
				recommendedConditions.removeAll(addedCondition);
			}
		} catch(ParseException e){
			e.printStackTrace();
		} catch(Exception e){
			e.printStackTrace();
		}
		
		
		return recommendedConditions;
	}
	
	private List<String> getRelatedPropertyByPropertyNames(String[] propertyNames) throws SQLException, ParseException{
		List<RecommendedCondition> relatedConditionList = new ArrayList<RecommendedCondition>();
		List<String> relatedPropertyNames = new ArrayList<String>();
		if(propertyNames == null)
			return relatedPropertyNames;
		String inStatementString = "(";
		for(String name : propertyNames){
			inStatementString += "'" + name + "',";
		}
		inStatementString = inStatementString.substring(0, inStatementString.length() - 1);
		inStatementString += ")";
		Statement stmt = connector.getConnection().createStatement();
		ResultSet rsResultSet = stmt.executeQuery("select relatedProperty from _ where property in " + inStatementString + ";");
		while(rsResultSet.next()){
			String resultStr = rsResultSet.getString("relatedProperty");
			String[] arrayResult = resultStr.split(",");
			for (String result : arrayResult) {
				String[] resultCondition = result.split(":");
				boolean exists = false;
				for(int idx = 0; idx < relatedConditionList.size(); ++idx){
					RecommendedCondition addedCond = relatedConditionList.get(idx);
					if(resultCondition[0].equals(addedCond.getFirst())){
						exists = true;
						relatedConditionList.get(idx).increaseStrength(Integer.parseInt(resultCondition[1]));
						break;
					}
				}
				if(exists == false){
					relatedConditionList.add(new RecommendedCondition(resultCondition[0], Integer.parseInt(resultCondition[1])));
				}
			}
		}
		
		Collections.sort(relatedConditionList);
		Collections.reverse(relatedConditionList);
		for(RecommendedCondition cond : relatedConditionList){
			relatedPropertyNames.add(cond.getFirst());
		}
		
		return relatedPropertyNames;
	}
	
}
